<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./Duty_Cycle_Generator.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Outputs a simple waveform which is high or low for a set number of cycles, then takes on the opposite state for a set number of cycles. If not immediately re-started, the output remains steady in its last state.">
<title>Duty Cycle Generator</title>
</head>
<body>

<p class="inline bordered"><b><a href="./Duty_Cycle_Generator.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>Duty Cycle Generator</h1>
<p>Outputs a simple waveform which is high or low for a set number of cycles,
 then takes on the opposite state for a set number of cycles. If not
 immediately re-started, the output remains steady in its last state.</p>
<p>One-shot by default: Pulse <code>start</code> high for one cycle to begin. Then
 <code>finish</code> pulses high for one cycle during the last clock cycle of the last
 phase of the <code>duty_cycle_out</code> output.  However, <code>finish</code> can be looped back
 to <code>start</code>, or <code>start</code> can be tied high, to generate a continuous waveform
 with a duty cycle and frequency determined by the <code>high_cycles</code> and
 <code>low_cycles</code> counts. <em>The cycle count for one phase is loaded during the
 last cycle of the previous phase.</em></p>
<p>Which phase comes first is set by the <code>first_phase</code> input. A value of <code>1</code>
 means the high phase comes first. Note that <code>first_phase</code> is only read at
 <code>start</code>.</p>
<p>Asserting <code>clear</code> immediately sets <code>duty_cycle_out</code> to <code>INITIAL_OUTPUT</code> and
 the <code>state</code> to <code>IDLE</code>.</p>
<p><strong>NOTE</strong>: The limit case of a cycle count of zero is equal to a cycle count of
 one. It takes one cycle to transition from phase to phase, so a zero length
 phase would result in a constant output, and while adding state transitions
 to support that is possible, it's pointless. If you need to stop the
 output, either assert <code>clear</code> or stop pulsing <code>start</code>.</p>
<h2>Use cases</h2>
<ul>
<li>Feeding a bit stream, synchronized to <code>start</code>, to <code>first_phase</code> will
 produce a Manchester-encoded version of the bit stream.</li>
<li>Altering the <code>high_cycles</code> and <code>low_cycles</code> values, while keeping their
 sum constant, produces a variable duty cycle signal of constant frequency,
 useful for driving servos, Pulse-Width Modulation, or to filter into a DC
 analog value.</li>
<li>Conversely, keeping the <code>high_cycles</code> and <code>low_cycles</code> ratio constant,
 but scaling their values up and down, preserves the duty cycle but alters
 the frequency of the output.</li>
<li>You can generate a framing signal for a bit stream to indicate which
 bits are header or body, based on the <code>start</code> of a frame.</li>
</ul>

<pre>
`default_nettype none

module <a href="./Duty_Cycle_Generator.html">Duty_Cycle_Generator</a>
#(
    parameter COUNT_WIDTH       = 0,
    parameter INITIAL_OUTPUT    = 1'b0
)
(
    input   wire                        clock,
    input   wire                        clear,

    input   wire                        start,
    output  reg                         finish,

    input   wire                        first_phase, // 0/1 -> low/high

    input   wire    [COUNT_WIDTH-1:0]   high_cycles,
    input   wire    [COUNT_WIDTH-1:0]   low_cycles,

    output  wire                        duty_cycle_out
);

    localparam COUNT_ZERO = {COUNT_WIDTH{1'b0}};

    initial begin
        finish = 1'b0;
    end
</pre>

<p>Define the states. We always output a low and a high phase, starting in
 either order, then we can either immediately start a new sequence (e.g.:
 going from <code>LOW_SECOND</code> to <code>LOW_FIRST</code>), or wait in <code>IDLE</code>. </p>

<pre>
    localparam STATE_WIDTH = 3;

    localparam [STATE_WIDTH-1:0] IDLE         = 'd0;
    localparam [STATE_WIDTH-1:0] LOW_FIRST    = 'd1;
    localparam [STATE_WIDTH-1:0] HIGH_SECOND  = 'd2;
    localparam [STATE_WIDTH-1:0] HIGH_FIRST   = 'd3;
    localparam [STATE_WIDTH-1:0] LOW_SECOND   = 'd4;
    // States 5 through 7 are unreachable. Could be checked as an error.

    wire [STATE_WIDTH-1:0] state;
    reg  [STATE_WIDTH-1:0] state_next = IDLE;
</pre>

<p>As the state changes, we load the necessary output value, otherwise the
 output remains steady.</p>

<pre>
    reg load_output_value   = 1'b0;
    reg output_value        = 1'b0;

    <a href="./Register.html">Register</a>
    #(
        .WORD_WIDTH     (1),
        .RESET_VALUE    (INITIAL_OUTPUT)
    )
    output_signal
    (
        .clock          (clock),
        .clock_enable   (load_output_value),
        .clear          (clear),
        .data_in        (output_value),
        .data_out       (duty_cycle_out)
    );
</pre>

<p>We count the number of clock cycles in each phase, signalling on the last
 cycle of each phase. (We can halt the count by loading a <code>phase_cycles</code> of
 zero, which we do in the IDLE state, which raises <code>div_by_zero</code>.)</p>

<pre>
    reg  [COUNT_WIDTH-1:0]  phase_cycles = COUNT_ZERO;
    wire                    end_of_phase;
    wire                    no_phase;
    reg                     phase_done = 1'b0;

    <a href="./Pulse_Divider.html">Pulse_Divider</a>
    #(
        .WORD_WIDTH         (COUNT_WIDTH),
        .INITIAL_DIVISOR    (COUNT_ZERO)
    )
    phase_duration
    (
        .clock              (clock),
        .restart            (1'b0),
        .divisor            (phase_cycles),
        .pulses_in          (1'b1),
        .pulse_out          (end_of_phase),
        .div_by_zero        (no_phase)
    );
</pre>

<p>We need to signal the end of phase continuously in the <code>IDLE</code> state so we
 can load a new cycle count right away when <code>start</code> is eventually asserted.
 In effect, it remembers that a phase has ended in the past, while we wait
 for an indeterminate time in <code>IDLE</code>. All other phase endings are handled
 immediately.</p>

<pre>
    always @(*) begin
        phase_done = (end_of_phase == 1'b1) || (no_phase == 1'b1);
    end
</pre>

<p>Define the possible actions on the system, independent of state, based on
 internal control signals and inputs. Here, that's the action to take at the
 end of a phase: we either do nothing or start a low or high phase.</p>

<pre>
    reg start_no_phase   = 1'b0;
    reg start_low_phase  = 1'b0;
    reg start_high_phase = 1'b0;

    always @(*) begin
        start_no_phase   = (phase_done == 1'b1) && (start == 1'b0);
        start_low_phase  = (phase_done == 1'b1) && (start == 1'b1) && (first_phase == 1'b0);
        start_high_phase = (phase_done == 1'b1) && (start == 1'b1) && (first_phase == 1'b1);
    end
</pre>

<p>Define the system transformations as a function of state and action.
 These are the edges on the state diagram.</p>

<pre>
    reg start_low_first         = 1'b0; // Start with the low phase first,
    reg low_done_to_high        = 1'b0; // then move to the high phase second.
    reg high_done               = 1'b0; // When high phase is done and we don't start a new phase
    reg high_done_start_low     = 1'b0; // When high phase is done and we start a low phase
    reg high_done_start_high    = 1'b0; // When high phase is done and we start another high phase

    reg start_high_first        = 1'b0; // Start with the high phase first,
    reg high_done_to_low        = 1'b0; // the move to the low phase second.
    reg low_done                = 1'b0; // When low phase is done and we don't start a new phase
    reg low_done_start_low      = 1'b0; // When low phase is done and we start another low phase
    reg low_done_start_high     = 1'b0; // When low phase is done and we start a high phase

    always @(*) begin
        start_low_first         = (state == IDLE)        && (start_low_phase  == 1'b1);
        low_done_to_high        = (state == LOW_FIRST)   && (phase_done       == 1'b1);
        high_done               = (state == HIGH_SECOND) && (start_no_phase   == 1'b1);
        high_done_start_low     = (state == HIGH_SECOND) && (start_low_phase  == 1'b1);
        high_done_start_high    = (state == HIGH_SECOND) && (start_high_phase == 1'b1);

        start_high_first        = (state == IDLE)        && (start_high_phase == 1'b1);
        high_done_to_low        = (state == HIGH_FIRST)  && (phase_done       == 1'b1);
        low_done                = (state == LOW_SECOND)  && (start_no_phase   == 1'b1);
        low_done_start_low      = (state == LOW_SECOND)  && (start_low_phase  == 1'b1);
        low_done_start_high     = (state == LOW_SECOND)  && (start_high_phase == 1'b1);
    end
</pre>

<p>Define the next state function: the state each transformation leads to.</p>

<pre>
    always @(*) begin
        state_next = (start_low_first       == 1'b1) ? LOW_FIRST    : state;
        state_next = (low_done_to_high      == 1'b1) ? HIGH_SECOND  : state_next;
        state_next = (high_done             == 1'b1) ? IDLE         : state_next;
        state_next = (high_done_start_low   == 1'b1) ? LOW_FIRST    : state_next;
        state_next = (high_done_start_high  == 1'b1) ? HIGH_FIRST   : state_next;

        state_next = (start_high_first      == 1'b1) ? HIGH_FIRST   : state_next;
        state_next = (high_done_to_low      == 1'b1) ? LOW_SECOND   : state_next;
        state_next = (low_done              == 1'b1) ? IDLE         : state_next;
        state_next = (low_done_start_low    == 1'b1) ? LOW_FIRST    : state_next;
        state_next = (low_done_start_high   == 1'b1) ? HIGH_FIRST   : state_next;
    end
    
    <a href="./Register.html">Register</a>
    #(
        .WORD_WIDTH     (STATE_WIDTH),
        .RESET_VALUE    (IDLE)
    )
    state_storage
    (
        .clock          (clock),
        .clock_enable   (1'b1),
        .clear          (clear),
        .data_in        (state_next),
        .data_out       (state)
    );
</pre>

<p>From the states and transformations, compute the control logic.</p>

<pre>
    always @(*) begin

        // Signal when we've completed the high/low pair of phases.

        finish = (phase_done == 1'b1) && ((state == LOW_SECOND) || (state == HIGH_SECOND));

        // When the current phase is done, load the next value for the next phase.
        // Checking the `state_next` is an optimization to prevent the
        // `output_signal` register from constantly re-loading while `IDLE`.
        // This isn't necessary, but having useless loads obscures function
        // and may waste power (when more than just a single bit like here).

        load_output_value = (phase_done == 1'b1) && (state_next != IDLE);

        // As we change states, what value should the output change to, or
        // stay steady with the current output (by omitting those transitions
        // here).

        output_value = (start_low_first      == 1'b1) ? 1'b0 : duty_cycle_out;
        output_value = (low_done_to_high     == 1'b1) ? 1'b1 : output_value;
        output_value = (high_done_start_low  == 1'b1) ? 1'b0 : output_value;
        output_value = (start_high_first     == 1'b1) ? 1'b1 : output_value;
        output_value = (high_done_to_low     == 1'b1) ? 1'b0 : output_value;
        output_value = (low_done_start_high  == 1'b1) ? 1'b1 : output_value;

        // As we change states, how long should the next phase last?
        // Otherwise, the phase remains steady by disabling the count with
        // a value of zero.

        phase_cycles = (start_low_first      == 1'b1) ? low_cycles  : COUNT_ZERO;
        phase_cycles = (low_done_to_high     == 1'b1) ? high_cycles : phase_cycles;
        phase_cycles = (high_done_start_low  == 1'b1) ? low_cycles  : phase_cycles;
        phase_cycles = (high_done_start_high == 1'b1) ? high_cycles : phase_cycles;
        phase_cycles = (start_high_first     == 1'b1) ? high_cycles : phase_cycles;
        phase_cycles = (high_done_to_low     == 1'b1) ? low_cycles  : phase_cycles;
        phase_cycles = (low_done_start_low   == 1'b1) ? low_cycles  : phase_cycles;
        phase_cycles = (low_done_start_high  == 1'b1) ? high_cycles : phase_cycles;
    end

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

